package quarto.controller.client.strategy;

import java.util.ArrayList;
import quarto.controller.client.Client;
import quarto.model.Board;
import quarto.model.InvalidPieceValueException;
import quarto.model.Piece;

/**
 * Representatie van een strategie voor de computer speler
 * @knows
 * - naam van de strategie
 * @does
 * - zetten bepalen aan de hand van een algoritme
 * @author Frank Borgonjen & Tim Smit
 */
public abstract class Strategy 
{
    /** bevat de huidige client */
    protected Client client;
    
    /** de naam van de strategie */
    protected String name;
    
    /**
     * Slaat de client op
     * @param client
     */
    public void setClient(Client client)
    {
        this.client = client;
    }
    
    /**
     * Geeft de naam terug van de strategie
     * @return naam van strategie
     */
    public String getName()
    {
        return this.name;
    }
    
    /**
     * Geeft een locatie voor het opgegeven stuk
     * @param piece
     * @return locatie van het stuk
     */
    public abstract int getLocationForPiece(Piece piece);
    
    /**
     * Geeft een nieuw stuk voor de tegenstander
     * @return het stuk
     */
    public abstract Piece getNewPiece();
    
    
    
    /**
     * Geeft de positie van een vakje waar het meegegeven piece op gezet 
     * moet worden om te winnen. Als deze positie niet bestaat wordt er -1
     * teruggegeven
     * @return  indien er een locatie bestaat waarop p gezet kan worden om te
     *          winnen, dan wordt die locatie teruggegeven. Anders -1
     */
    protected int getWinLocation(Board board, Piece piece)
    {
        // initialisatie
        int bestLocation = -1;
        int i = 0;
        
        // door het bord heenlopen
        while (i < Board.DIM * Board.DIM)
        {
            // is het vakje leeg
            if (board.isEmpty(i))
            {
                // zet het stuk op het bord
                board.setPiece(i, piece);

                // kijken of er een winnaar is
                if (board.hasWinner())
                {
                    // kijken of het de eerste winnende plek is,
                    // of random
                    if (bestLocation == -1 || Math.random() > 0.6)
                    {
                        bestLocation = i;
                    }
                }

                // vakje weer leeg maken
                board.setPiece(i, null);
                
                // het stuk weer terug stoppen bij de beschikbare stukken
                board.addPiece(piece);
            }
            
            i++;
        }
        
        return bestLocation;
    }
    
    /**
     * Geeft een willekeurige beschikbare locatie terug
     * @require er moet nog een plek vrij zijn
     * @return willekeurige locatie
     */
    protected int getRandomLocation()
    {
        Board board = this.client.getBoard();
        int randomLocation = -1;
        
        // net zolang een nieuwe random locatie kiezen totdat deze niet leeg is
        do
        {
            // een random vakje kiezen
            randomLocation = (int)(Math.random() * 16);

            // is het vakje beschikbaar op het bord
            if (!board.isEmpty(randomLocation))
            {
                randomLocation = -1;
            }
        }
        while (randomLocation == -1);
        
        return randomLocation;
    }
    
    /**
     * Geeft een willekeurig beschikbaar stuk terug
     * @require er moet nog een stuk beschikbaar zijn
     * @return willekeurig stuk
     */
    protected Piece getRandomPiece()
    {
        // beschilkbare stukken ophalen
        ArrayList<Piece> pieces = this.client.getBoard().getAvailablePieces();
        
        // willekeurig stuk kiezen
        int i = (int) (Math.random() * pieces.size());

        // het terug te geven stuk
        return pieces.get(i);
    }
}
